﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace BioinformaticAlgoritms2014
{
    public static class Extensions
    {
        public static string Reverse(this string s)
        {
            char[] charArray = s.ToCharArray();
            Array.Reverse(charArray);
            return new string(charArray);
        }

        public static string GetComplement(this string src)
        {
            return new string(src.ToCharArray().Where(a => ComplementDict.ContainsKey(a)).Select(a => ComplementDict[a]).ToArray());
        }
        private static Dictionary<char, char> ComplementDict = new Dictionary<char, char>() { { 'A', 'T' }, { 'T', 'A' }, { 'C', 'G' }, { 'G', 'C' } };
        private static List<char> nucleChars = new List<char>(){'A','C','G','T'}; 

        public static string ToCustomString(this IEnumerable<string> arr)
        {
            return string.Join(" ", arr);
        }

        public static string ToCustomString(this IEnumerable<int> arr)
        {
            return arr.Select(a => a.ToString()).ToArray().ToCustomString();
        }

        internal static int MaxMatchesInWindow(this Match match, int winLength)
        {
            int length = winLength - match.Pattern.Length;
            return match.Indexes.Select(index => match.Indexes.Where(a => a >= index && a <= index + length).Count()).Concat(new[] { 0 }).Max();
        }

        internal static int[] GetMinSkewIndexes(int[] skew)
        {
            var min = skew.Min();
            return
                skew.Select((a, i) => new { Val = a, Index = i }).Where(a => a.Val == min).Select(a => a.Index).ToArray();
        }

        public static int HammingDistance(string seq1, string seq2)
        {
            if (seq2.Length != seq1.Length)
                throw new ArgumentException("Error  argument string length", "seq2");
            int hamming = 0;
            for (int i = 0; i < seq1.Length; i++)
            {
                if (seq1[i] != seq2[i])
                {
                    hamming++;
                }
            }
            return hamming;
        }

        public static string[] GetNeighborhoodPatterns(string pattern, int d)
        {
           return GetAllDnaWords(pattern.Length).Where(a => HammingDistance(pattern, a) <= d).ToArray();
        }

        public static IEnumerable<String> GetAllDnaWords(int length)
        {
            if (length <= 0)
                yield break;

            for (int i=0;i<nucleChars.Count;i++)
            {
                char c = nucleChars[i];
                if (length > 1)
                {
                    foreach (String restWord in GetAllDnaWords(length - 1))
                        yield return c + restWord;
                }
                else
                    yield return "" + c;
            }
        }
    }
}
